"""
数据处理模块 - 负责传感器数据解析和格式转换
"""
import struct
import re
import json
from datetime import datetime
from typing import Dict, Any, Optional
from core.event_bus import event_bus, EventType
from core.config import Config

class SensorData:
    """传感器数据模型"""
    def __init__(self, sensor_id: int):
        self.sensor_id = sensor_id
        self.water_content = 0.0
        self.temperature = 0.0
        self.power_voltage = 0.0
        self.last_update = datetime.now()

class DataProcessor:
    """数据处理器"""
    
    def __init__(self):
        self.sensor_data: Dict[int, SensorData] = {}
        self.power_voltage = 0.0
        
        # 订阅串口数据事件
        event_bus.subscribe(EventType.SERIAL_DATA_RECEIVED, self._handle_serial_data)
    
    def _handle_serial_data(self, frame_data: str):
        """处理串口数据帧"""
         # 若是下载管理器广播的原始字节流，这里直接忽略
        try:
            parsed_frame = self._parse_frame(frame_data)
            if parsed_frame:
                self._process_message(parsed_frame)
        except Exception as e:
            print(f"数据处理错误：{e}")
    
    def _parse_frame(self, frame: str) -> Optional[Dict[str, str]]:
        """解析数据帧"""
        try:
            return {
                'cmd_head': frame[:2],          # 帧头
                'cmd_type': frame[2:4],         # 命令类型(UPDATE_CONTROL)如，0xB1
                'ctrl_msg': frame[4:6],         # 指示消息的类型,如，0x10/0x07接收mcu信息
                'screen_id': frame[6:10],       # 产生消息的画面ID
                'control_id': frame[10:14],     # 产生消息的控件ID  1bytes
                'param': frame[14:-8],          # 可变长度参数
                'cmd_tail': frame[-8:]          # 帧尾
            }
        except Exception as e:
            print(f"帧解析异常: {e}, 帧数据为: {frame}")
            return None
    
    def _process_message(self, frame: Dict[str, str]):
        """处理消息"""
        cmd_type = frame['cmd_type']
        ctrl_msg = frame['ctrl_msg']
        
        if cmd_type == Config.CMD_TYPES['SENSOR_DATA']:
            if ctrl_msg == Config.CTRL_MSG_TYPES['NOTIFY_INT_TEXT']:
                self._NotifyIntText(frame)
            elif ctrl_msg == Config.CTRL_MSG_TYPES['NOTIFY_TEXT']:
                self._NotifyText(frame)
            

    # 接收整型和浮点数据处理
    def _NotifyIntText(self, frame):  # Dict[str, str]
        """
          brief 
          details 
          param screen_id 画面ID
                control_id 控件ID
                state 按钮状态:0弹起,1按下
        """
        try:
            screen_id = frame['screen_id'][-2:]
            control_id = frame['control_id'][-2:]
            param = frame['param']
            
            if len(param) != 12:
                return
                
            sign = param[:2]       # 数据类型：00无符号、01有符号整型、02单精度浮点型、03双精度浮点型
            fill_zero = param[2:4]  # 填充零：不足补0
            float_data = param[4:]
            
            if len(float_data) != 8:
                return
                
            float_num = struct.unpack('>f', bytes.fromhex(param[4:]))[0]
            
            if screen_id == '00':
                if control_id == '03':
                    self.power_voltage = float_num
                    # 更新所有传感器的电压数据
                    for sensor_data in self.sensor_data.values():
                        sensor_data.power_voltage = float_num
                
            else:
                sensor_id = int(screen_id)
                if sensor_id not in self.sensor_data:
                    self.sensor_data[sensor_id] = SensorData(sensor_id)
                
                sensor = self.sensor_data[sensor_id]
                
                if control_id == '01':
                    sensor.water_content = float_num
                elif control_id == '02':
                    sensor.temperature = float_num
                
                sensor.power_voltage = self.power_voltage
                sensor.last_update = datetime.now()
                
                # 发送传感器数据更新事件
                event_bus.emit(EventType.SENSOR_DATA_UPDATED, {
                    'sensor_id': sensor_id,
                    'water_content': sensor.water_content,
                    'temperature': sensor.temperature,
                    'power_voltage': sensor.power_voltage
                })
                
        except Exception as e:
            print(f"浮点数据处理异常：{e}")

    # 接收文本处理
    def _NotifyText(self, frame: Dict[str, str]):
        """
        brief  文本控件通知  
        details  当文本通过屏幕按键更新，执行此函数
        param screen_id 画面ID
              control_id 控件ID
              text     文本内容
        """
        try:
            screen_id = frame['screen_id'][-2:]
            control_id = frame['control_id'][-2:]
            text_hex = frame['param']
            # 解码文本
            ascii_text = None
            try:
                ascii_text = bytes.fromhex(text_hex).decode('ascii')
            except UnicodeDecodeError:
                try:
                    ascii_text = bytes.fromhex(text_hex).decode('utf-8', errors='ignore')
                except:
                    print('未解析出来')
                    return
            if not ascii_text:
                print(f"文本解码失败: {text}")
                return
            
            # 新增：处理配置JSON（设备发的是 0x10 文本类型）
            if screen_id == '00' and control_id == '04':
                try:
                    cfg_header = json.loads(ascii_text)
                    event_bus.emit(EventType.CONFIG_HEADER_UPDATED, cfg_header)
                except Exception as e:
                    print(f"配置JSON解析失败: {e}")
                return
            
            # 检查是否为时间格式
            if self._is_datetime_format(ascii_text):
                device_time = datetime.strptime(ascii_text, "%Y-%m-%d %H:%M:%S")
                event_bus.emit(EventType.DEVICE_TIME_UPDATED, {
                    'device_time': device_time,
                    'local_time': datetime.now()
                })
                return

            # 处理数值浮点数据
            try:
                value = float(ascii_text)
                if screen_id == '00' and control_id == '01':
                    # 设备返回的时间间隔
                    interval_text = self._seconds_to_interval_text(int(value))
                    event_bus.emit(EventType.DEVICE_SAMPLING_INTERVAL, {
                        'type': 'interval_update',
                        'seconds': value,
                        'text': interval_text
                    })
            except ValueError:
                if ascii_text == "Error":
                    event_bus.emit(EventType.DEVICE_DISCONNECTED, "设备报告错误")
                    
        except Exception as e:
            print(f"文本数据处理错误：{e}")
    
    def _is_datetime_format(self, text: str) -> bool:
        """检查是否为日期时间格式"""
        patterns = [
            r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$',
            r'^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}$',
            r'^\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}$',
            r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$'
        ]
        return any(re.match(pattern, text) for pattern in patterns)
    
    def _seconds_to_interval_text(self, total_seconds: int) -> str:
        """将秒数转换为时间间隔文本"""
        for option in Config.INTERVAL_OPTIONS:
            if self._parse_interval_time(option) == total_seconds:
                return option
        
        if total_seconds < 60:
            return f"{total_seconds}s"
        elif total_seconds < 3600:
            minutes = total_seconds // 60
            return f"{minutes}m"
        else:
            hours = total_seconds // 3600
            remaining_minutes = (total_seconds % 3600) // 60
            if remaining_minutes == 0:
                return f"{hours}h"
            else:
                return f"{hours}h{remaining_minutes}m"
    
    def _parse_interval_time(self, interval_text: str) -> int:
        """解析时间间隔文本为秒数"""
        interval_text = interval_text.replace(" ", "")
        total_seconds = 0
        
        # 匹配小时
        hour_match = re.search(r'(\d+)h', interval_text)
        if hour_match:
            total_seconds += int(hour_match.group(1)) * 3600
            
        # 匹配分钟
        minute_match = re.search(r'(\d+)m', interval_text)
        if minute_match:
            total_seconds += int(minute_match.group(1)) * 60
            
        # 匹配秒
        second_match = re.search(r'(\d+)s', interval_text)
        if second_match:
            total_seconds += int(second_match.group(1))
            
        return total_seconds
    
    def get_sensor_data(self, sensor_id: int) -> Optional[SensorData]:
        """获取指定传感器数据"""
        return self.sensor_data.get(sensor_id)
    
    def get_all_sensor_data(self) -> Dict[int, SensorData]:
        """获取所有传感器数据"""
        return self.sensor_data.copy()